package com.tsinghua.server.common;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class RequestSandbox {

    @Value("${sandbox.secret}")
    static String secret;

    @Value("${sandbox.restcode}")
    static String restcode;

    @Value("${sandbox.ip}")
    static String ip;

    @Value("${sandbox.dbID}")
    static String dbID;

    @Value("${sandbox.datatype}")
    static String datatype;

    @Value("${sandbox.tableName}")
    static String tableName;

    public static String getData(String sql, Integer currPage, Integer pageSize) throws UnsupportedEncodingException {
        return RequestSandbox.httpGet(RequestSandbox.getUrl(sql,currPage,pageSize).toString());
    }
    public static String getData(String sql) throws UnsupportedEncodingException {
        return RequestSandbox.httpGet(RequestSandbox.getUrl(sql,null,null).toString());
    }

    public static String httpGet(String url) throws UnsupportedEncodingException {
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response;
        try {
            // 获取相应结果
            response = closeableHttpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            // 对HttpEntity操作的工具类
            String toStringResult = EntityUtils.toString(entity, StandardCharsets.UTF_8);
            System.out.println(toStringResult);  // 会把网站内容都打印出来
            // 确保输入流关闭
            EntityUtils.consume(entity);
            return toStringResult;
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            if(closeableHttpClient != null) {
                try {
                    closeableHttpClient.close();
                } catch(IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static StringBuilder getUrl(String sql, Integer currPage, Integer pageSize) throws UnsupportedEncodingException {
        String secret = "h5vqGvKw3geRbw544ekRjMMGrBFcVpjN";
        String ip = "8.131.224.124";
        SecretBuilder secretBuilder = new SecretBuilder(secret, ip);
        String restcode = "appsecrit";
        String dbID = "1";
        String datatype = "0";
        String tableName = "fx_ctmxsrsjzh";

        secretBuilder.setTitle("SQL查询")
                .add("dbID", dbID)
                .add("fun", "searchsql")
                .add("restcode", restcode)
                .add("sql", sql);

        if(currPage != null) {
            secretBuilder.add("curPage", currPage.toString());
        }
        if(pageSize !=null){
            secretBuilder.add("pageSize", pageSize.toString());
        }

        String restCheck = secretBuilder.getRestCheck();
        StringBuilder url = new StringBuilder();
        url.append("http://" + ip + "/sandboxapi.html?");
        for (Map.Entry<String, String> entry : secretBuilder.params.entrySet()) {
            if (entry.getKey().equals("sql")){
                url.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(),StandardCharsets.UTF_8.name())).append('&');
            } else {
                url.append(entry.getKey()).append('=').append(entry.getValue()).append('&');
            }
        }
        url.deleteCharAt(url.length() - 1);
        url.append('&').append("restcheck=").append(restCheck);
        System.out.println("url为");
        System.out.println(url);

        return url;
    }

    public static String getMD5(String orgString, boolean isUpperCase) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(orgString.getBytes("utf-8"));
            byte b[] = md.digest();

            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            String ret = buf.toString();
            if (isUpperCase)
                return ret.toUpperCase();
            else
                return ret;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    static class SecretBuilder {
        String secret;
        String ip;
        String title;
        TreeMap<String, String> params = new TreeMap<>(); // TreeMap保证遍历时的顺序，以生成正确的secret

        public SecretBuilder(String secret, String ip) {
            this.secret = secret;
            this.ip = ip;
        }

        public SecretBuilder add(String key, String value) {
            params.put(key, value);
            return this;
        }

        public SecretBuilder setTitle(String title) {
            this.title = title;
            return this;
        }

        public String getRestCheck() throws UnsupportedEncodingException {
            StringBuilder urlSb = new StringBuilder();
            StringBuilder newUrlSb = new StringBuilder();

            urlSb.append("http://" + ip + "/sandboxapi.html?");

            // secret生成
            StringBuilder secretSb = new StringBuilder();
            Long resttime = new Date().getTime();
            add("resttime", resttime.toString());

            for (Map.Entry<String, String> entry : params.entrySet()) {
                secretSb.append(entry.getKey()).append('=').append(entry.getValue()).append('&');
            }
            secretSb.deleteCharAt(secretSb.length() - 1);

            // url生成
            urlSb.append(secretSb);
            String restcheck = getMD5(secretSb + secret, false);



            return restcheck;
        }

        public void clear() {
            params.clear();
            title = "";
        }

        public String getTitle() {
            return title;
        }
    }
}
